home *** CD-ROM | disk | FTP | other *** search
- Path: news.crd.ge.com!rebecca!rpi!not-for-mail
- From: rcauvin@natinst.com (Roger L. Cauvin)
- Newsgroups: comp.lang.c++,comp.lang.c++.moderated
- Subject: Comparison Operators Solution (was Re: Virtual function question)
- Date: 10 Apr 1996 18:28:21 -0000
- Organization: National Instruments
- Sender: cppmods@netlab.cs.rpi.edu
- Approved: Dietmar.Kuehl@uni-konstanz.de
- Message-ID: <4kguk5$5au@netlab.cs.rpi.edu>
- References: <4jp6e9$ou5@dub-news-svc-1.compuserve.com> <4ked7o$8g3@dub-news-svc-1.compuserve.com>
- NNTP-Posting-Host: netlab.cs.rpi.edu
- X-Original-Date: 10 Apr 1996 17:45:52 GMT
-
- In article <4ked7o$8g3@dub-news-svc-1.compuserve.com>, RossBoylan@aol.com
- (Ross Boylan) wrote:
-
- > Problem: To define the comparison operators <, <=, >, ==, etc in
- > terms of one or two primitives (< and maybe ==), so that all classes
- > for which the comparisons make sense only require definition of the
- > primitives.
- >
- > Solutions
- > 1) The best solution I've seen is in the Standard Template library
- >
- > My original problem statement used member functions, but the symmetric
- > free-standing functions are more appropriate to the comparison
- > operators.
- >
- > 2) The remaining solutions use member functions (Borland's library
- > apparently does this) and create bogus functions which take abstract
- > classes as arguments. In the following, RBMagnitude::operator< is not
- > virtual, so subclasses do not need to override it (they ignore it
- > instead).
- > 3) Several people suggested casting down as a possibility
- >
- > 4) My original problem defined all RBMagnitude operators as virtual.
- > I have some potential subclasses which redefine all the inequality
- > operators. However, the gain in computing comparisons directly may be
- > offset by the overhead of virtual functions, and it is probably
- > clearner not to use virtual functions.
- >
- > 5) Scott Meyer's new book, More Effective C++, has some material in
- > item 33 which may be relevant (I haven't had a chance to look at it
- > yet).
-
- I consider none of the "solutions" offered above to be ideal. A solution
- that I do consider to be ideal is similar to the second proposal.
- Conceptually, any class of objects that allows comparison operations
- is-a-kind-of comparable object. So how about a ComparableObject abstract
- base class? It should actually be a class template: a number is
- comparable to other numbers and to native numeric types, a string is
- comparable to other strings and to native C strings. The template
- parameter specifies the type of the value with which a ComparableObject
- can be compared. Concrete classes such as Number and String are derived
- from ComparableObject template class(es).
-
- The following solution maximizes code sharing and concepual clarity, and
- allows overriding of all the comparison operations:
-
- template <class ValueType>
- class ComparableObject
- {
- public:
- friend bool operator==(const ComparableObject &comparableObject,
- ValueType value);
- friend bool operator==(ValueType value, const ComparableObject
- &comparableObject);
- friend bool operator!=(const ComparableObject &comparableObject,
- ValueType value);
- friend bool operator!=(ValueType value, const ComparableObject
- &comparableObject);
- friend bool operator<(const ComparableObject &comparableObject,
- ValueType value);
- friend bool operator<(ValueType value, const ComparableObject
- &comparableObject);
- friend bool operator<=(const ComparableObject &comparableObject,
- ValueType value);
- friend bool operator<=(ValueType value, const ComparableObject
- &comparableObject);
- friend bool operator>(const ComparableObject &comparableObject,
- ValueType value);
- friend bool operator>(ValueType value, const ComparableObject
- &comparableObject);
- friend bool operator>=(const ComparableObject &comparableObject,
- ValueType value);
- friend bool operator>=(ValueType value, const ComparableObject
- &comparableObject);
-
- protected:
- virtual bool IsEqualTo(ValueType value) = 0;
- virtual bool IsNotEqualTo(ValueType value);
- virtual bool IsLessThan(ValueType value) = 0;
- virtual bool IsLessThanOrEqualTo(ValueType value);
- virtual bool IsGreaterThan(ValueType value);
- virtual bool IsGreaterThanOrEqualTo(ValueType value);
-
- private:
- };
-
- Comparison operators in ComparableObject are implemented as calls to
- protected virtual functions. E.g.:
-
- bool operator!=(const ComparableObject &comparableObject, ValueType value)
- {
- return comparableObject.IsNotEqualTo(value);
- }
-
- The protected virtual functions are implemented in terms of the equal to
- and less than operations:
-
- bool ComparableObject::IsNotEqualTo(ValueType value)
- {
- return !IsEqualTo(value);
- }
-
- Derived classes need only provide implementations for IsEqualTo and IsLessThan:
-
- class Number : public virtual ComparableObject<const Number &>,
- public virtual ComparableObject<double>
- {
- public:
-
- protected:
- virtual bool IsEqualTo(const Number &value);
- virtual bool IsLessThan(const Number &value);
- virtual bool IsEqualTo(double value);
- virtual bool IsLessThan(double value);
-
- private:
- };
-
- The Number class now supports all comparison operations by defining them
- in terms of two primitive operations per value type. This solution is
- superior to STL's function templates for at least two reasons. First, all
- operations are overridable by derived classes. Second, there are fewer
- template instantiations than in STL's technique.
-
-
- Roger
-
- ---
-
- Roger L. Cauvin
- rcauvin@natinst.com
- Software Engineer
- National Instruments
-
- [ Articles to moderate: mailto:c++-submit@netlab.cs.rpi.edu ]
- [ Read the C++ FAQ: http://www.connobj.com/cpp/cppfaq.htm ]
- [ Moderation policy: http://www.connobj.com/cpp/guide.htm ]
- [ Comments? mailto:c++-request@netlab.cs.rpi.edu ]
-